#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define N 64
#define SIZE 1024
char* argv[N];//指针数组，放命令行字符串的子串
char pwd[SIZE];//目录
char env[SIZE];//环境变量
int lastcode = 0;//退出码

char* HostName()//获取主机名
{
    char* hostname = getenv("HOSTNAME");
    if(hostname) return hostname;
    else return "none";
}

char* UserName()//获取用户名
{
    char* username = getenv("LOGNAME");
    if(username) return username;
    else return "none";
}

char* CurPath()//获取当前路径
{
    char* curpath = getenv("PWD");
    if(curpath) return curpath;
    else return "none";
}

char* Home()//获取家目录
{
    return getenv("HOME");
}

int Interactive(char commandline[], int size)
{
    printf("%s@%s:~%s$ ", UserName(), HostName(), CurPath());
    //输入
    fgets(commandline, SIZE, stdin);
    commandline[strlen(commandline)-1] = 0;//解决最后一个\n和空串
    return strlen(commandline);
}
void Split(char commandline[])
{
    int i = 0;
    argv[i++] = strtok(commandline, " ");
    while(argv[i++] = strtok(NULL, " "));
    if(strcmp("ls", argv[0]) == 0)//颜色
    {
        argv[i-1] = "--color";
        argv[i] = NULL;
    }
}
void Execute()
{
    pid_t id = fork();
    if(id == 0)//让子进程执行
    {
        //用程序替换
        execvp(argv[0], argv);
        exit(1);
    }
    //父进程回收
    int status = 0;
    pid_t rid = waitpid(id, &status, 0);
    if(rid == id) lastcode = WEXITSTATUS(status);//获得退出码
}

int BuildCmp()
{
    int ret = 0;
    if(strcmp("cd", argv[0]) == 0)
    {
        ret = 1;
        char* target = argv[1];//得到第二个字符
        if(!target) target = Home();//是空直接到家目录
        chdir(target);//更改当前工作目录
        //把当前工作目录交给另一个变量，防止 cd.. 
        char temp[500];//小一点。。。
        getcwd(temp, 500);
        //同步环境变量
        snprintf(pwd, SIZE, "PWD=%s", temp);
        putenv(pwd);//环境变量修改
    }
    else if(strcmp("export", argv[0]) == 0)
    {
        //export是给bash的，不是子进程的，否则不会被所有子进程继承
        ret = 1;
        if(argv[1])
        {
            strcpy(env, argv[1]);
            putenv(env);
        }
    }
    else if(strcmp("echo", argv[0]) == 0)
    {
        ret = 1;
        if(argv[1] == NULL)
        {
            printf("\n");
        }
        else 
        {
            if(argv[1][0] == '$')
            {
                if(argv[1][1] == '?')
                {
                    printf("%d\n", lastcode);
                }
                else 
                {
                    printf("\n");
                }
            }
            else 
            {
                printf("%s\n", argv[1]);
            }
        }
    }
    return ret;
}

int main()
{
    while(1)
    {
        //1、显示命令行，输入字符串
        char commandline[SIZE];
        int n = Interactive(commandline, SIZE);
        if(n == 0) continue;

        //2、分割输入的命令行字符串
        Split(commandline);

        //3、执行内建命令——cd（目录切换）和export导环境变量
        n = BuildCmp();
        if(n) continue;//是1不执行指令
        
        //4、执行命令，创建子进程
        Execute();
    }
    

    //printf("task: %s\n",commandline);
    
    return 0;
}